package com.breeze.components.web.core;

import com.breeze.components.core.exception.ApiException;
import com.breeze.components.core.exception.error.ErrorCode;
import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.apache.skywalking.apm.toolkit.trace.TraceContext;

/**
 * 响应信息主体
 *
 * @author breeze
 */
@Data
public class ResponseDTO<T> {

  @Schema(description = "请求id")
  String requestId;

  @Schema(description = "时间戳")
  Integer timestamp;

  @Schema(description = "响应code")
  private Integer code;

  @Schema(description = "响应msg")
  private String msg;

  @Schema(description = "响应体", nullable = true)
  @JsonInclude
  private T data;

  public ResponseDTO(String requestId, Integer timestamp, Integer code, String msg, T data) {
    this.requestId = requestId;
    this.timestamp = timestamp;
    this.code = code;
    this.msg = msg;
    this.data = data;
  }

  public static <T> ResponseDTO<T> ok() {
    return build(null, ErrorCode.OK.code(), ErrorCode.OK.message());
  }

  public static <T> ResponseDTO<T> ok(T data) {
    return build(data, ErrorCode.OK.code(), ErrorCode.OK.message());
  }

  public static <T> ResponseDTO<T> fail() {
    return build(
        null,
        ErrorCode.Business.OPERATE_FAIL_ERROR.code(),
        ErrorCode.Business.OPERATE_FAIL_ERROR.message());
  }

  public static <T> ResponseDTO<T> fail(T data) {
    return build(
        data,
        ErrorCode.Business.OPERATE_FAIL_ERROR.code(),
        ErrorCode.Business.OPERATE_FAIL_ERROR.message());
  }

  public static <T> ResponseDTO<T> fail(ApiException exception) {
    return build(null, exception.getErrorCode().code(), exception.getMessage());
  }

  public static <T> ResponseDTO<T> fail(ApiException exception, T data) {
    return build(data, exception.getErrorCode().code(), exception.getMessage());
  }

  public static <T> ResponseDTO<T> build(T data, Integer code, String msg) {
    return new ResponseDTO<>(
        TraceContext.traceId(), (int) (System.currentTimeMillis() / 1000), code, msg, data);
  }
}
